﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using C4F.VistaP2P.Common;

namespace C4F.VistaP2P.Win.Picture
{
    [Description("Use this control with the NetworkManager to share pictures"),
     ToolboxBitmap(typeof(resfinder), "C4F_P2PWinformControls.c4f.bmp"),
    Designer(typeof(PictureDesigner))]
    public partial class PictureControl : UserControl
    {
        public PictureControl()
        {
            InitializeComponent();
            btnSendPicture.Click += new EventHandler(_SendPictureButton_Click);
        }

#region public methods and events to use when completely overriding this control

        public void SendPicture(string fullPathAndFileName)
        {
            //send it in another thread so the UI thread remains responsive...  
            if (fullPathAndFileName != null && System.IO.File.Exists(fullPathAndFileName))
            {
                FileStream fs = new FileStream(fullPathAndFileName, FileMode.Open);
                PicturePacket packet = new PicturePacket();
                packet.s = fs;
                packet.fileName = System.IO.Path.GetFileName(fullPathAndFileName);
                MetadataFileInfo md = new MetadataFileInfo();
                md.ReadMetaData(fullPathAndFileName);
                packet.title = md.Title;
                
                if (SendingPicture != null)
                {
                    SendingPicture(this, new PictureChangedEventArgs(packet));
                }         
            }
            else
            {
                throw new ApplicationException(string.Format("File not found: {0}", fullPathAndFileName));
            }
        }

        public event EventHandler<PictureChangedEventArgs> PictureReceived;
        public event EventHandler<StatusChangedEventArgs> StatusChanged;

        
#endregion

        #region Properties

        private PictureBox mPictureBox = null;
        /// <summary>
        /// 
        /// </summary>
        /// <value></value>
        [
           Description(""),
           Category("P2P/controls")
        ]
        public PictureBox PictureBox
        {
            get
            {
                if (mPictureBox == null)
                    return pbImage;
                else
                    return mPictureBox;
            }
            set
            {
                mPictureBox = value;
                if (value != null)
                {
                    pbImage.Visible = false;
                }
                else
                {
                    pbImage.Visible = true;
                    Show();
                }
            }
        }

        //Have to shadow the visible property for smart tag..
        [
            Description("Visible"),
            Category("Visible"),

         ]
        public bool ShadowVisible
        {
            get
            {
                return Visible;
            }
            set
            {
                Visible = value;
            }
        }

        private Button mSendPictureButton = null;
        /// <summary>
        /// 
        /// </summary>
        /// <value></value>
        [
           Description(""),
           Category("P2P/controls")
           
        ]
        public Button SendPictureButton
        {
            get
            {
                if (mSendPictureButton == null)
                    return btnSendPicture;
                else
                    return mSendPictureButton;
            }
            set
            {
                //if we previously registered for a button, unregister for it.
                if (mSendPictureButton != null)
                {
                    mSendPictureButton.Click -= new EventHandler(_SendPictureButton_Click);
                }

                mSendPictureButton = value;
                if (value != null)
                {
                    //unregister for the default event
                    btnSendPicture.Visible = false;
                    btnSendPicture.Click -= new EventHandler(_SendPictureButton_Click);

                    //register for the new controls event
                    mSendPictureButton = value;
                    mSendPictureButton.Click += new EventHandler(_SendPictureButton_Click);

                }
                else
                {
                    btnSendPicture.Visible = true;
                    btnSendPicture.Click += new EventHandler(_SendPictureButton_Click);
                    Show();
                }
            }
        }

        #endregion

        internal event EventHandler<PictureChangedEventArgs> SendingPicture;
        private void _SendPictureButton_Click(object sender, EventArgs e)
        {

            Microsoft.Win32.OpenFileDialog ofd;
            ofd = new Microsoft.Win32.OpenFileDialog();
            ofd.FileName = "openFileDialog1";
            ofd.Filter = "(*.JPG, *.GIF, *.PNG)|*.jpg;*.gif;*.png|All Files (*.*)|*.*";
            ofd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            ofd.RestoreDirectory = true;
            ofd.Title = "Select a Picture";


            //check return value, but how in wpf?
            bool ok = (bool)ofd.ShowDialog();

            if (ok)
            {
                SendPicture(ofd.FileName);                                   
            }
        }


        /// <summary>
        /// _StatusChangedHandler delegate used to ensure that the control is only changed by the thread that created it.
        /// look for crossthreading issues for more information.
        /// </summary>
        /// <param name="userName">The username of the NetworkManager tha this Chat control is connected to</param>
        /// <param name="e">The Status changed Event</param>
        /// <param name="state"></param>
        private delegate void SetConnectionStatusHandler(SystemState state);
        internal void SetConnectionStatus(SystemState state)
        {
            if (SendPictureButton.InvokeRequired)
            {
                SendPictureButton.Invoke(new SetConnectionStatusHandler(SetConnectionStatus), state);
            }
            else
            {
                if (state == SystemState.LoggedIn)
                {                    
                    SendPictureButton.Enabled = true;
                }
                else if (state == SystemState.LoggedOut)
                {
                    SendPictureButton.Enabled = false;                
                }
            }
        }

        private delegate void _StatusChangedHandler(string userName, StatusChangedEventArgs e);
        internal void SetStatusChanged(string userName, StatusChangedEventArgs e)
        {
            if (SendPictureButton.InvokeRequired)
            {
                SendPictureButton.Invoke(new _StatusChangedHandler(SetStatusChanged), new object[] { userName, e });
            }
            else
            {
                if (userName == e.Member && e.NewNodeJoined)
                {
                    SendPictureButton.Enabled = true;
                }

                if (userName == e.Member && e.NodeLeft)
                {
                    SendPictureButton.Enabled = false;
                }

                //let anyone else know if they registered for the event.
                if (null != StatusChanged)
                {
                    StatusChanged(userName, e);
                }
            }
        }

        delegate void SetNewPictureHandler(PictureChangedEventArgs packet);
        internal void SetNewPicture(PictureChangedEventArgs e)
        {
            if (PictureBox.InvokeRequired)
            {
                // Invocation required
                PictureBox.Invoke( new SetNewPictureHandler(SetNewPicture), e);
            }
            else
            {
                Byte[] b = new Byte[C4F.VistaP2P.Common.PictureHelper.MAX_IMAGE_SIZE];
                int curPos = 0;
                int val = 0;
                do
                {
                    if (e.Packet.s.CanRead)
                    {
                        val = e.Packet.s.Read(b, curPos, C4F.VistaP2P.Common.PictureHelper.MAX_IMAGE_SIZE - curPos);
                        curPos += val;
                    }
                    else
                    {
                        throw new ApplicationException("Unable to Read the Picture Stream");
                    }
                } while (val != 0);

                MemoryStream ms = new MemoryStream();
                ms.Write(b, 0, curPos);
                ms.Position = 0;

                Bitmap bm = new Bitmap(ms);
                PictureBox.Image = bm;

                //display meta data sent with the packet.
                lblTitleValue.Text = e.Packet.title;
                lblFileNameValue.Text = e.Packet.fileName;

                //TODO: seek to origin for stream before raising event?
                if (PictureReceived != null)
                {
                    PictureReceived(this, e);
                }                
            }
        }
    }
}
